
/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2021原作者。
 *
 *根据Apache许可证2.0版（“许可证”）获得许可；
 *除非符合许可证，否则不得使用此文件。
 *您可以在以下地址获取许可证副本：
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证分发的内容是按“原样”分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限和
 *许可证下的限制。
 */

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Parameter;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * Public delegate for resolving autowirable parameters on externally managed
 * constructors and methods.
 *
 * @author Sam Brannen
 * @author Juergen Hoeller
 * @since 5.2
 * @see #isAutowirable
 * @see #resolveDependency
 */
/**
 *用于解析外部管理的自动连接参数的公共委托
 *构造函数和方法。
 *
 *@作者Sam Brannen
 *@作者Juergen Hoeller
 *@自5.2
 *@参见#isAutowirable
 *@参见#resolveDependency
 */
public final class ParameterResolutionDelegate {

	private static final AnnotatedElement EMPTY_ANNOTATED_ELEMENT = new AnnotatedElement() {
		@Override
		@Nullable
		public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
			return null;
		}
		@Override
		public Annotation[] getAnnotations() {
			return new Annotation[0];
		}
		@Override
		public Annotation[] getDeclaredAnnotations() {
			return new Annotation[0];
		}
	};


	private ParameterResolutionDelegate() {
	}


	/**
	 * Determine if the supplied {@link Parameter} can <em>potentially</em> be
	 * autowired from an {@link AutowireCapableBeanFactory}.
	 * <p>Returns {@code true} if the supplied parameter is annotated or
	 * meta-annotated with {@link Autowired @Autowired},
	 * {@link Qualifier @Qualifier}, or {@link Value @Value}.
	 * <p>Note that {@link #resolveDependency} may still be able to resolve the
	 * dependency for the supplied parameter even if this method returns {@code false}.
	 * @param parameter the parameter whose dependency should be autowired
	 * (must not be {@code null})
	 * @param parameterIndex the index of the parameter in the constructor or method
	 * that declares the parameter
	 * @see #resolveDependency
	 */
	/**
	 *确定所提供的｛@link参数｝是否可能＜em＞＜/em＞
	 *从｛@link AutowireCapableBeanFactory｝自动连线。
	 *＜p＞如果提供的参数带注释或
	 *用{@link Autowired@Autowired}注释的meta，
	 *｛@link Qualifier@Qualifier｝或｛@linkValue@Value｝。
	 *＜p＞注意｛@link#resolveDependency｝可能仍然能够解析
	 *即使此方法返回｛@code false｝。
	 *@param parameter依赖项应自动连接的参数
	 *（不能为｛@code null｝）
	 *@param parameterIndex构造函数或方法中参数的索引
	 *声明参数的
	 *@参见#resolveDependency
	 */
	public static boolean isAutowirable(Parameter parameter, int parameterIndex) {
		Assert.notNull(parameter, "Parameter must not be null");
		AnnotatedElement annotatedParameter = getEffectiveAnnotatedParameter(parameter, parameterIndex);
		return (AnnotatedElementUtils.hasAnnotation(annotatedParameter, Autowired.class) ||
				AnnotatedElementUtils.hasAnnotation(annotatedParameter, Qualifier.class) ||
				AnnotatedElementUtils.hasAnnotation(annotatedParameter, Value.class));
	}

	/**
	 * Resolve the dependency for the supplied {@link Parameter} from the
	 * supplied {@link AutowireCapableBeanFactory}.
	 * <p>Provides comprehensive autowiring support for individual method parameters
	 * on par with Spring's dependency injection facilities for autowired fields and
	 * methods, including support for {@link Autowired @Autowired},
	 * {@link Qualifier @Qualifier}, and {@link Value @Value} with support for property
	 * placeholders and SpEL expressions in {@code @Value} declarations.
	 * <p>The dependency is required unless the parameter is annotated or meta-annotated
	 * with {@link Autowired @Autowired} with the {@link Autowired#required required}
	 * flag set to {@code false}.
	 * <p>If an explicit <em>qualifier</em> is not declared, the name of the parameter
	 * will be used as the qualifier for resolving ambiguities.
	 * @param parameter the parameter whose dependency should be resolved (must not be
	 * {@code null})
	 * @param parameterIndex the index of the parameter in the constructor or method
	 * that declares the parameter
	 * @param containingClass the concrete class that contains the parameter; this may
	 * differ from the class that declares the parameter in that it may be a subclass
	 * thereof, potentially substituting type variables (must not be {@code null})
	 * @param beanFactory the {@code AutowireCapableBeanFactory} from which to resolve
	 * the dependency (must not be {@code null})
	 * @return the resolved object, or {@code null} if none found
	 * @throws BeansException if dependency resolution failed
	 * @see #isAutowirable
	 * @see Autowired#required
	 * @see SynthesizingMethodParameter#forExecutable(Executable, int)
	 * @see AutowireCapableBeanFactory#resolveDependency(DependencyDescriptor, String)
	 */
	/**
	 *从
	 *提供了｛@link AutowireCapableBeanFactory｝。
	 *＜p＞为各个方法参数提供全面的自动布线支持
	 *与Spring针对自动连线字段的依赖注入设施和
	 *方法，包括对{@link Autowired@Autowired}的支持，
	 *｛@link Qualifier@Qualifier｝和支持属性的｛@linkValue@Value｝
	 *｛@code@Value｝声明中的占位符和SpEL表达式。
	 *＜p＞除非参数被注释或元注释，否则依赖项是必需的
	 *使用｛@link Autowired@Autowired｝，需要｛@linkAutowired#｝
	 *标志设置为｛@code false｝。
	 *＜p＞如果未声明显式＜em＞限定符＜/em＞，则参数的名称
	 *将用作解决歧义的限定符。
	 *@param parameter应该解析其依赖关系的参数（不能是
	 *｛@code null｝）
	 *@param parameterIndex构造函数或方法中参数的索引
	 *声明参数的
	 *@param containingClass包含参数的具体类；这可能
	 *不同于声明参数的类，因为它可能是子类
	 *可能替换类型变量（不能为｛@code null｝）
	 *@param beanFactory要解析的｛@code AutowireCapableBeanFactory｝
	 *依赖项（不能为｛@code null｝）
	 *@返回解析的对象，如果未找到，则返回｛@code null｝
	 *如果依赖关系解析失败，@throws BeansException
	 *@参见#isAutowirable
	 *@参见所需的自动连线#
	 *@参见SynthesizingMethodParameter#for Executable（Executable，int）
	 *@参见AutowireCapableBeanFactory#resolveDependency（DependencyDescriptor，字符串）
	 */
	@Nullable
	public static Object resolveDependency(
			Parameter parameter, int parameterIndex, Class<?> containingClass, AutowireCapableBeanFactory beanFactory)
			throws BeansException {

		Assert.notNull(parameter, "Parameter must not be null");
		Assert.notNull(containingClass, "Containing class must not be null");
		Assert.notNull(beanFactory, "AutowireCapableBeanFactory must not be null");

		AnnotatedElement annotatedParameter = getEffectiveAnnotatedParameter(parameter, parameterIndex);
		Autowired autowired = AnnotatedElementUtils.findMergedAnnotation(annotatedParameter, Autowired.class);
		boolean required = (autowired == null || autowired.required());

		MethodParameter methodParameter = SynthesizingMethodParameter.forExecutable(
				parameter.getDeclaringExecutable(), parameterIndex);
		DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required);
		descriptor.setContainingClass(containingClass);
		return beanFactory.resolveDependency(descriptor, null);
	}

	/**
	 * Due to a bug in {@code javac} on JDK versions prior to JDK 9, looking up
	 * annotations directly on a {@link Parameter} will fail for inner class
	 * constructors.
	 * <p>Note: Since Spring 6 may still encounter user code compiled with
	 * {@code javac 8}, this workaround is kept in place for the time being.
	 * <h4>Bug in javac in JDK &lt; 9</h4>
	 * <p>The parameter annotations array in the compiled byte code excludes an entry
	 * for the implicit <em>enclosing instance</em> parameter for an inner class
	 * constructor.
	 * <h4>Workaround</h4>
	 * <p>This method provides a workaround for this off-by-one error by allowing the
	 * caller to access annotations on the preceding {@link Parameter} object (i.e.,
	 * {@code index - 1}). If the supplied {@code index} is zero, this method returns
	 * an empty {@code AnnotatedElement}.
	 * <h4>WARNING</h4>
	 * <p>The {@code AnnotatedElement} returned by this method should never be cast and
	 * treated as a {@code Parameter} since the metadata (e.g., {@link Parameter#getName()},
	 * {@link Parameter#getType()}, etc.) will not match those for the declared parameter
	 * at the given index in an inner class constructor.
	 * @return the supplied {@code parameter} or the <em>effective</em> {@code Parameter}
	 * if the aforementioned bug is in effect
	 */
	/**
	 *由于JDK 9之前的JDK版本上的｛@code javac｝中存在错误，请查找
	 *对于内部类，直接在｛@link Parameter｝上的注释将失败
	 *构造函数。
	 *＜p＞注意：由于Spring 6仍然可能遇到使用
	 *｛@codejavac8｝，此解决方法暂时保留。
	 *＜h4＞JDK中javac中的错误&lt；9</h4>
	 *＜p＞编译字节码中的参数注释数组排除了一个条目
	 *对于内部类的隐式＜em＞封闭实例＜/em＞参数
	 *构造函数。
	 *<h4>解决方法</h4>
	 *＜p＞此方法通过允许
	 *调用方访问前面｛@link Parameter｝对象上的注释（即。，
	 *｛@code索引-1｝）。如果提供的｛@code索引｝为零，则此方法返回
	 *空｛@code AnnotatedElement｝。
	 *<h4>警告</h4>
	 *＜p＞此方法返回的｛@code AnnotatedElement｝不应强制转换
	 *由于元数据（例如｛@link Parameter#getName（）｝，
	 *｛@link Parameter#getType（）｝等）将与声明的参数不匹配
	 *在内部类构造函数中的给定索引处。
	 *@返回提供的｛@code参数｝或＜em＞有效＜/em＞｛@codeParameter｝
	 *如果上述错误有效
	 */
	private static AnnotatedElement getEffectiveAnnotatedParameter(Parameter parameter, int index) {
		Executable executable = parameter.getDeclaringExecutable();
		if (executable instanceof Constructor && ClassUtils.isInnerClass(executable.getDeclaringClass()) &&
				executable.getParameterAnnotations().length == executable.getParameterCount() - 1) {
			// Bug in javac in JDK <9: annotation array excludes enclosing instance parameter
			// JDK<9中javac中的错误：注释数组排除封闭实例参数
			// for inner classes, so access it with the actual parameter index lowered by 1
			// 对于内部类，请使用实际参数索引降低1来访问它
			return (index == 0 ? EMPTY_ANNOTATED_ELEMENT : executable.getParameters()[index - 1]);
		}
		return parameter;
	}

}
